﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;

namespace ConsoleTestLocalHost1
{
    class Program
    {


        private const int CtrlCEvent = 0;//CTRL_C_EVENT = 0;//一个Ctrl+C的信号被接收，该信号或来自键盘，或来自GenerateConsoleCtrlEvent    函数   

        private const int CtrlBreakEvent = 1;//CTRL_BREAK_EVENT = 1;//一个Ctrl+Break信号被接收，该信号或来自键盘，或来自GenerateConsoleCtrlEvent    函数  

        private const int CtrlCloseEvent = 2;//CTRL_CLOSE_EVENT = 2;//当用户系统关闭Console时，系统会发送此信号到此   

        private const int CtrlLogoffEvent = 5;//CTRL_LOGOFF_EVENT = 5;//当用户退出系统时系统会发送这个信号给所有的Console程序。该信号不能显示是哪个用户退出。   

        private const int CtrlShutdownEvent = 6;//CTRL_SHUTDOWN_EVENT = 6;//当系统将要关闭时会发送此信号到所有Console程序   

        public delegate bool ConsoleCtrlDelegate(int dwCtrlType);
        [DllImport("kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handlerRoutine, bool add);

        static bool HandlerRoutine(int ctrlType)
        {
            switch (ctrlType)
            {
                case CtrlCEvent: Console.WriteLine("Ctrl+C keydown"); break;

                case CtrlBreakEvent: Console.WriteLine("Ctrl+Break keydown"); break;

                case CtrlCloseEvent:
                    Console.WriteLine("window closed");
                    rvr_s.p.Close();
                    break;

                case CtrlLogoffEvent: Console.WriteLine("log off or shut down"); break;

                case CtrlShutdownEvent: Console.WriteLine("system shut down"); break;

                default: Console.WriteLine(ctrlType.ToString()); break;
            }
            return false;
        }
        static private RVR_PXL_Server rvr_s;
        static void Main(string[] args)
        {

            if (SetConsoleCtrlHandler(new ConsoleCtrlDelegate(HandlerRoutine), true))
            {
                Console.WriteLine("Set    SetConsoleCtrlHandler    success!!");
            }
            else
            {
                Debug.WriteLine("Set    SetConsoleCtrlHandler    Error!!");
                //AsReportFile.WriteFile("", "test.txt", "who close?");
            }

            //SocketServer s = new SocketServer();
            rvr_s = new RVR_PXL_Server();
            SocketClient c = new SocketClient();

            DateTime before = DateTime.Now;

            //string test = "01234567890123456789";
            string test = "62C44F7500000000340032003400333933302E7C";
            //byte[] buff = new byte[20]
            //{   //62 C4 4f 75 00 00 00 00 34 00 32 00 34 00 33 39 33 30 2e 7c
            //    0x62, 0xC4, 0x4F, 0x75, 0x00,
            //    0x00, 0x00, 0x00, 0x00, 0x34,
            //    0x00, 0x32, 0x00, 0x34, 0x00,
            //    0x39, 0x33, 0x30, 0x2E, 0x7C,
            //};
            //string test = System.Text.Encoding.UTF8.GetString(buff);// "62C44f7500000000340032003400333933302e7c";

            for (int i = 0; i<1000;i++)
            {
                c.WriteLine(test);
            }

            while (c.counter < 1000) { };

            //c.counter = 0;
            //DateTime mid = DateTime.Now;
            //for (int i = 0; i < 1000; i++)
            //{
            //    c.WriteLine(test);
            //}

            //while (c.counter < 1000) { };

            DateTime after = DateTime.Now;

            Console.WriteLine("TimeUsed:" + (after - before).TotalMilliseconds.ToString() + " ms");

            while (true)
            {
                string s_input = Console.ReadLine();
                c.WriteLine(s_input);
            }

        }

        public class SocketServer
        {
            public Socket socket_server;

            public static int ServerPort = 50005;
            public static string ServerAddress = "127.0.0.1";
            public static ProtocolType type = ProtocolType.Tcp;
            public Thread thread_server_process;


            public SocketServer()
            {
                IPAddress ip = IPAddress.Parse(ServerAddress);
                socket_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, type);
                socket_server.Bind(new IPEndPoint(ip, ServerPort));
                socket_server.Listen(1);
                Console.WriteLine("Start Listen");
                thread_server_process = new Thread(ServerProcess);
                thread_server_process.Start();

            }

            public void ServerProcess()
            {
                Console.WriteLine("Start Thread");
                Socket clientSocket = socket_server.Accept();
                byte[] buffer = new byte[1024];
                while (true)
                {
                    int len = clientSocket.Receive(buffer);
                    //Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer.Take(len).ToArray()));
                    clientSocket.Send(buffer,0, len, SocketFlags.None);
                }
            }
        }

        public class RVR_PXL_Server
        {
            public Process p;

            public RVR_PXL_Server()
            {
                ProcessStartInfo ps = new ProcessStartInfo();
                ps.FileName = "RVR_PXL/RVR FW Decoder Tool.exe";
                ps.UseShellExecute = false;
                p = Process.Start(ps);
                p.Start();
            }
        }

        public class SocketClient
        {
            public int counter = 0;
            public Socket socket_client;
            public Thread thread_client_process;
            public SocketClient()
            {
                IPAddress ip = IPAddress.Parse(SocketServer.ServerAddress);
                EndPoint ep = new IPEndPoint(ip, SocketServer.ServerPort);
                socket_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, SocketServer.type);
                socket_client.Connect(ep);
                thread_client_process = new Thread(ClientProcess);
                thread_client_process.Start();
            }

            public void ClientProcess()
            {
                byte[] rx_buffer = new byte[1024];
                while (true)
                {
                    if(buffer_tx.Count == 0)
                    {
                        Thread.Sleep(10);
                        continue;
                    }

                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(buffer_tx[0]);
                    buffer_tx.RemoveAt(0);

                    socket_client.Send(buffer);
                    int ack_cnt = socket_client.Receive(rx_buffer);
                    byte[] ack = rx_buffer.Take(ack_cnt).ToArray();

                    //Console.WriteLine(System.Text.Encoding.UTF8.GetString(ack));

                    counter++;
                    //if (!buffer.SequenceEqual(ack))
                    //{
                    //    Console.WriteLine("err_ack");
                    //}
                    //else
                    //{
                    //    counter++;
                    //}
                }
            }

            private List<string> buffer_tx = new List<string>();

            public void WriteLine(string s)
            {
                buffer_tx.Add(s);
            }
        }
    }
}
